#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "RoomManagerSubsystem.generated.h"

DECLARE_LOG_CATEGORY_EXTERN(RoomManager, Log, All)

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FActorEnterRoomSignature, FName, RoomName, AActor*, InActor);

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FActorLeaveRoomSignature, FName, RoomName, AActor*, InActor);

USTRUCT()
struct PHOBIA_API FRoomActorInfo
{
	GENERATED_BODY()

	UPROPERTY(Transient)
	TArray<TObjectPtr<AActor>> RoomActor;
};

USTRUCT()
struct PHOBIA_API FRoomInfo
{
	GENERATED_BODY()

	UPROPERTY(Transient)
	TMap<TObjectPtr<AActor>, FRoomActorInfo> ActorMap;
};

/**
 * 
 */
UCLASS()
class PHOBIA_API URoomManagerSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()

protected:
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;
	virtual void Deinitialize() override;

public:
	UFUNCTION(BlueprintCallable)
	void AddActorToRoom(const FName& RoomName, AActor* InRoomActor, AActor* InActor);

	UFUNCTION(BlueprintCallable)
	void RemoveActorFromRoom(const FName& RoomName, AActor* InRoomActor, AActor* InActor);

	UFUNCTION(BlueprintCallable)
	bool IsRoomExist(const FName& RoomName) const;

	UFUNCTION(BlueprintCallable)
	bool IsActorInRoom(const FName& RoomName, AActor* InActor) const;

	UFUNCTION(BlueprintCallable)
	bool IsActorInAnyRoom(AActor* InActor) const;

	UFUNCTION(BlueprintCallable)
	FName GetActorRoomName(AActor* InActor) const;

protected:
	void AddToRoomImpl(const FName& RoomName, AActor* InActor);
	void RemoveFromRoomImpl(const FName& RoomName, AActor* InActor);

public:
	UPROPERTY(BlueprintAssignable)
	FActorEnterRoomSignature OnActorEnterRoom;

	UPROPERTY(BlueprintAssignable)
	FActorLeaveRoomSignature OnActorLeaveRoom;

private:
	UPROPERTY(Transient)
	TMap<FName, FRoomInfo> RoomInfoMap;

	UPROPERTY(Transient)
	TMap<TObjectPtr<AActor>, FName> ActorMap;
};
